﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SQLCompact;
using System.IO;
using PictureOrganizer3.Properties;
using BrightIdeasSoftware;

namespace PictureOrganizer3
{
    public partial class ComicForm : Form
    {
        private log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private Dictionary<int, string> validRatings = new Dictionary<int, string> { 
        { 0, "" },
        { 1, "01 - sehr schlecht" },
        { 2, "02" },
        { 3, "03 - schlecht" },
        { 4, "04" },
        { 5, "05 - geht so" },
        { 6, "06" },
        { 7, "07 - gut" },
        { 8, "08" },
        { 9, "09" },
        { 10, "10 - sehr gut" }
        };
        private Database ctx;
        private string originalFolderName;
        private bool folderNameHasBeenChanged = false;

        public ComicForm(Comic comic, Database ctx)
        {
            InitializeComponent();

            Text = String.Format(Text, comic.Name);
            this.ctx = ctx;
            tb_Pages.Text = comic.Pictures.Count.ToString();
            originalFolderName = comic.FolderName;
            // Beim Start wird für jedes Bild erstmal ein Platzhalter hinzugefügt, 
            // bis das echte Bild vom Background-Worker geladen wurde.
            comic.Pictures.ToList().ForEach(p => imageList.Images.Add(p.Name, Resources.defaultImage));
            olvColumnPicture.ImageGetter = p => ((Picture)p).Name;

            cb_Rating.DataSource = validRatings.ToList<KeyValuePair<int, string>>();
            cb_Rating.DisplayMember = "Value";
            cb_Rating.ValueMember = "Key";

            LoadAuthors(ctx);

            cb_Author.SelectedItem = comic.Author;
            cb_Author.SelectedIndexChanged += new EventHandler(cb_Author_SelectedIndexChanged);

            comicBindingSource.Add(comic);
            dataListView.DataSource = comic.Pictures;
            dataListView.View = View.LargeIcon;

            comic.PropertyChanged += new PropertyChangedEventHandler(comic_PropertyChanged);

            SetThumbnail(comic);
        }

        private void LoadAuthors(Database ctx)
        {
            cb_Author.DataSource = ctx.Authors.ToList(); ;
            cb_Author.DisplayMember = "Name";
            //cb_Author.ValueMember = "Id";
        }

        void comic_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var comic = (Comic)sender;

            if (e.PropertyName.Equals("IsRead"))
            {
                if (comic.IsRead)
                    comic.ReadDate = DateTime.Now;
                else
                    comic.ReadDate = null;
            }
            else
            {
                string newFolderName = String.Format(
                    "[{0}] {1} {2}{3}{4}{5}",
                    comic.Author != null ? comic.Author.Name : "",
                    comic.Name,
                    comic.IsColored ? "[col]" : "",
                    comic.IsUncensored ? "[uncensored]" : "",
                    comic.IsRescan ? "[rescan]" : "",
                    !string.IsNullOrWhiteSpace(comic.Language) ? "[" + comic.Language + "]" : "").Trim();

                if (!comic.FolderName.Equals(newFolderName))
                {
                    comic.FolderName = newFolderName;
                    folderNameHasBeenChanged = true;
                }
            }
            tsbtn_Save.Enabled = true;
        }

        private void SetThumbnail(Comic comic)
        {
            // Wenn kein Thumbail hinterlegt ist, dann abbrechen
            if (comic.DisplayImageId == null)
                return;

            var picture = comic.Pictures.Where(p => p.Id == comic.DisplayImageId).Single();

            using (FileStream s = File.OpenRead(Path.Combine(comic.DirectoryPath, comic.FolderName, picture.Name)))
            {
                this.pictureBox.Image = Image.FromStream(s);
            }
        }

        private void tsbtn_Save_Click(object sender, EventArgs e)
        {
            ctx.SubmitChanges();
            if (folderNameHasBeenChanged)
            {
                Comic c = (Comic)comicBindingSource[0];
                Directory.Move(Path.Combine(c.DirectoryPath, originalFolderName), Path.Combine(c.DirectoryPath, c.FolderName));
            }

            tsbtn_Save.Enabled = false;
        }

        private void loadImageWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Comic comic = (Comic)comicBindingSource[0];
            foreach (var picture in comic.Pictures.OrderBy(p => p.Name))
            {
                if (loadImageWorker.CancellationPending) return;

                UpdateImage(picture.Name, GetThumbnail(Path.Combine(picture.Comic.DirectoryPath, picture.Comic.FolderName, picture.Name), 128, 128));
            }
        }

        private delegate void UpdateImageDelegate(string key, Image image);
        private void UpdateImage(string key, Image image)
        {
            if (this.InvokeRequired)
            {
                UpdateImageDelegate d = new UpdateImageDelegate(UpdateImage);
                try
                {
                    this.Invoke(d, key, image);
                }
                catch (Exception ex)
                {
                    logger.Warn("Das aktualisieren des Forms ist gescheitet, da es bereits gelöscht wurde.", ex);
                }
            }
            else
            {
                dataListView.BeginUpdate();
                imageList.Images.RemoveByKey(key);
                imageList.Images.Add(key, image);
                dataListView.EndUpdate();
            }
        }

        public Image GetThumbnail(string fileName, int width, int height)
        {
            Image i;
            using (FileStream s = File.OpenRead(fileName))
            {
                i = Image.FromStream(s).GetThumbnailImage(width, height, new Image.GetThumbnailImageAbort(() => false), IntPtr.Zero);
            }
            return i;
        }

        private void ComicForm_Load(object sender, EventArgs e)
        {
            loadImageWorker.RunWorkerAsync();
        }

        private void dataListView_DoubleClick(object sender, EventArgs e)
        {
            var picture = (Picture)((DataListView)sender).SelectedObject;
            System.Diagnostics.Process.Start(Path.Combine(picture.Comic.DirectoryPath, picture.Comic.FolderName, picture.Name));
        }

        private void dataListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            var picture = (Picture)((DataListView)sender).SelectedObject;
            if (picture == null) return;
            // Nur wen das ausgewählte Bild nicht das aktuelle Thumbnail ist, wird der Button zum Ändern des Thumbnail aktiviert
            tsbtn_SetAsThumbnail.Enabled = !picture.Comic.DisplayImageId.Equals(picture.Id);
        }

        private void tsbtn_SetAsThumbnail_Click(object sender, EventArgs e)
        {
            var picture = (Picture)dataListView.SelectedObject;
            var comic = (Comic)comicBindingSource[0];
            comic.DisplayImageId = picture.Id;

            SetThumbnail(comic);
        }

        private void btn_AddAuthor_Click(object sender, EventArgs e)
        {
            using (var dlg = new AddAuthorForm(ctx))
            {
                if (dlg.ShowDialog(this) == DialogResult.OK)
                {
                    // Der ComboBox die neue Liste von Autoren zuweisen
                    LoadAuthors(ctx);
                    // Und anschließend auch dem Comic den grad angelegten Author zuweisen
                    cb_Author.SelectedItem = dlg.Author;
                }
            }
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            loadImageWorker.CancelAsync();
        }

        private void cb_Author_SelectedIndexChanged(object sender, EventArgs e)
        {
            ((Comic)comicBindingSource[0]).Author = (Author)((ComboBox)sender).SelectedItem;
        }
    }
}
